import calendar
import time
import jwt
from django.conf import settings
from django.core.cache import cache
from utils.exceptions.CustomJwtExpiredException import CustomJwtExpiredException
from utils.exceptions.CustomParamsException import CustomParamsException

class JwtServices:
    """
    Jwt服务类
    """

    # 生成token
    def createToken(self, obj=dict(), type=None):
        # 过期时间
        now = calendar.timegm(time.gmtime())
        exp = calendar.timegm(time.gmtime()) + int(settings.JWT_EXP[0])
        params = {
            'exp': exp,  # 过期时间
            'iat': now,  # 开始时间
            'iss': settings.JWT_ISS[0],  # 签名
            'data': obj,
        }
        # 加密生成字符串
        token = jwt.encode(
            params,
            settings.JWT_SECRET[0],
            algorithm=settings.JWT_ALG[0])
        # token进行缓存
        self.setTokenCache(token, int(settings.JWT_EXP[0]))
        # 返回token
        ret = {
            'token_type': 'Bearer',
            'token': token,
            'expires_time': exp,
            'params': obj
        }
        # 没给类型则给个刷新token
        if not type:
            res = self.createRefreshToken(obj)
            if res:
                ret = dict(ret, **res)
        # 返回参数
        return ret

    def parseToken(self, request):
        payload = self.getRequestToken(request)
        if not payload:
            raise CustomParamsException('请求头token必须')
        token = payload.lstrip('Bearer').strip()
        try:
            ret = jwt.decode(token, settings.JWT_SECRET[0], algorithms=[settings.JWT_ALG[0]])
        except Exception as e:
            raise CustomJwtExpiredException('签名已过期')
        now = calendar.timegm(time.gmtime())
        if not ret['exp'] or now > ret['exp']:
            raise CustomJwtExpiredException('签名已过期')
        # 将用户信息注入请求体
        request.userInfo = ret['data']
        return ret


    # 存储缓存
    def setTokenCache(self, token, exp):
        return cache.set(token, token, exp)

    # 生成刷新token
    def createRefreshToken(self, obj=dict()):
        # 过期时间
        now = calendar.timegm(time.gmtime())
        exp = calendar.timegm(time.gmtime()) + int(settings.JWT_RE_EXP[0])
        params = {
            'exp': exp,  # 过期时间
            'iat': now,  # 开始时间
            'iss': settings.JWT_ISS[0],  # 签名
            'data': obj,
        }
        # 加密生成字符串
        token = jwt.encode(
            params,
            settings.JWT_SECRET[0],
            algorithm=settings.JWT_ALG[0])
        # token进行缓存
        self.setTokenCache(token,int(settings.JWT_RE_EXP[0]))
        # 返回token
        ret = {
            'refresh_token': token,
            'refresh_expires_time': exp,
        }
        # 返回参数
        return ret

    # 判断token是否在缓存中
    def checkTokenFromCache(self, token):
        return cache.get(token)

    # 删除缓存中的token
    def delTokenFromCache(self, token):
        return cache.set(token, '', 0)  # 10分钟

    # 获取缓存中的token
    def getRequestToken(self, request):
        token = request.META.get('HTTP_AUTHORIZATION')
        return token
